﻿/* 
 =============================================================================
 * Program Name 	: gen_code.h
 * Author		: #B96902133, Hakki Caner Kirmizi
 * Date			: 20100615
 * Description		: An interface to code generation according to the
 * 			  semantic action coming from parser.
 * Environment		: Windows-7 Entreprise
 * Editor		: vim 7.2 for WIN 
 * Integration Tests	: linux2.csie.ntu.edu.tw
 * Flex			: 2.5.35
 * Bison		: bison (GNU Bison) 2.4.1
 * Compiler		: gcc (Debian 4.4.4-5) 4.4.4
 * Version Control	: TortoiseSVN 1.6.8, Build 19260 - 32 Bit
 * Project Hosting	: http://code.google.com/p/csie-compiler/
 *
 =============================================================================
 */


enum code_ops {
	INVOKESTATIC=0, L, GOTO, RETURN,
	ILOAD, ALOAD, IALOAD, AALOAD, LDC,
	ISTORE, ASTORE, IASTORE,
	NEWARRAY, MULTIANEWARRAY,
	IADD, ISUB, IMUL, IDIV, INEG,
	IAND, IOR, IXOR,
	IFEQ, IFNE, IFGE, IFGT, IFLE, IFLT,
	IFICMPEQ, IFICMPNE, IFICMPGE, IFICMPGT, IFICMPLE, IFICMPLT,
	LOCAL_VAR_NUM, LABEL_NUM, READINT, PRINTLNINT
};

char *op_name[] = { "invokestatic", "L", "goto", "return",
		    "iload", "aload", "iaload", "aaload", "ldc",
		    "istore", "astore", "iastore",
		    "newarray int", "multianewarray int",
		    "iadd", "isub", "imul", "idiv", "ineg",
			"iand", "ior", "ixor",
		    "ifeq", "ifne", "ifge", "ifgt", "ifle", "iflt",
		    "if_icmpeq", "if_icmpne", "if_icmpge", "if_icmpgt", "if_icmple", "if_icmplt"
};

char *io_name[] = { "int readInt() @ StdIO", 
		    "void printInt(int) @ StdIO",
		    "void printlnInt(int) @ StdIO"
};

void gen_global_main(FILE *out) {
	char class_str[] = ".class Program\n\n";
	char method_init_str[] = ".method void <init>()\n";
	char method_main_str[] = ".method public static void main(String[])\n";
	char aload_str[] = "\taload #0\n";
	char invoke_spe_str[] = "\tinvokespecial void <init>() @ Object\n";
	char return_str[] = "\treturn\n\n";
	
	fprintf(out, class_str);
	fprintf(out, method_init_str);
	fprintf(out, aload_str);
	fprintf(out, invoke_spe_str);
	fprintf(out, return_str);
	fprintf(out, method_main_str);
}

void gen_code(FILE *out, enum code_ops op, int arg) {
	switch(op) {
		case INVOKESTATIC:
			fprintf(out, "\t%s ", op_name[op]);
			break;
		case L:
			fprintf(out, "%s%d:", op_name[op], arg);
			break;
		case GOTO:
			fprintf(out, "\t%s L%d\n", op_name[op], arg);
			break;
		case RETURN:
			fprintf(out, "\t%s\n", op_name[op]);
			break;
		case ILOAD:
			fprintf(out, "\t%s #%d\n", op_name[op], arg);
			break;
		case IALOAD:
			fprintf(out, "\t%s\n", op_name[op]);
			break;
		case ALOAD:
			fprintf(out, "\t%s #%d\n", op_name[op], arg);
			break;
		case AALOAD:
			fprintf(out, "\t%s\n", op_name[op]);
			break;
		case LDC:
			fprintf(out, "\t%s %d\n", op_name[op], arg);
			break;
		case ISTORE:
			fprintf(out, "\t%s #%d\n", op_name[op], arg);
			break;
		case ASTORE:
			fprintf(out, "\t%s #%d\n", op_name[op], arg);
			break;
		case IASTORE:
			fprintf(out, "\t%s\n", op_name[op]);
			break;
		case NEWARRAY:
			fprintf(out, "\t%s\n", op_name[op]);
			break;
		case MULTIANEWARRAY:
			if (arg == 2) 
				fprintf(out, "\t%s[][] %d-d\n", op_name[op], arg);
			else if (arg == 3)
				fprintf(out, "\t%s[][][] %d-d\n", op_name[op], arg);
			else if (arg == 4)
				fprintf(out, "\t%s[][][][] %d-d\n", op_name[op], arg);
			else if (arg == 5)
				fprintf(out, "\t%s[][][][][] %d-d\n", op_name[op], arg);
			else if (arg == 6)
				fprintf(out, "\t%s[][][][][][] %d-d\n", op_name[op], arg);
			else if (arg == 7)
				fprintf(out, "\t%s[][][][][][][] %d-d\n", op_name[op], arg);
			else if (arg == 8)
				fprintf(out, "\t%s[][][][][][][][] %d-d\n", op_name[op], arg);
			else if (arg == 9)
				fprintf(out, "\t%s[][][][][][][][][] %d-d\n", op_name[op], arg);
			else if (arg == 10)
				fprintf(out, "\t%s[][][][][][][][][][] %d-d\n", op_name[op], arg);
			break;
		case IADD:
			fprintf(out, "\t%s\n", op_name[op]);
			break;
		case ISUB:
			fprintf(out, "\t%s\n", op_name[op]);
			break;
		case IMUL:
			fprintf(out, "\t%s\n", op_name[op]);
			break;
		case IDIV:
			fprintf(out, "\t%s\n", op_name[op]);
			break;
		case INEG:
			fprintf(out, "\t%s\n", op_name[op]);
			break;
		case IAND:
			fprintf(out, "\t%s\n", op_name[op]);
			break;
		case IOR:
			fprintf(out, "\t%s\n", op_name[op]);
			break;
		case IXOR:
			fprintf(out, "\t%s\n", op_name[op]);
			break;
		case IFEQ:
			fprintf(out, "\t%s L%d\n", op_name[op], arg);
			break;
		case IFICMPGE:
			fprintf(out, "\t%s L%d\n", op_name[op], arg);
			break;
		case IFICMPGT:
			fprintf(out, "\t%s L%d\n", op_name[op], arg);
			break;
		case IFICMPLE:
			fprintf(out, "\t%s L%d\n", op_name[op], arg);
			break;
		case IFICMPLT:
			fprintf(out, "\t%s L%d\n", op_name[op], arg);
			break;
		case IFICMPEQ:
			fprintf(out, "\t%s L%d\n", op_name[op], arg);
			break;
		case IFICMPNE:
			fprintf(out, "\t%s L%d\n", op_name[op], arg);
			break;
		case LOCAL_VAR_NUM:
			fprintf(out, "#%d\n", arg);
			break;
		case LABEL_NUM:
			fprintf(out, "L%d:\n", arg);
			break;
		case READINT:
			fprintf(out, "%s\n", io_name[0]);
			break;
		case PRINTLNINT:
			fprintf(out, "%s\n", io_name[2]);
			break;
		default:
			printf("//Not implemented | op: %d arg: %d\n", op, arg);
			break;
	}
}
